"use strict";

let {webServerFileUpdateModule, webServerDataUpdate} = require("./updateFileModule");

let {wakeUpCurrentNetworkPointHost, wakeUpCurrentNetworkALLHost} = require('./networkWakeUp');

/**@deprecated
 * 获取Web服务器响应中间件请求数据，非Form-Data表单，没有获取到数据，返回null*/
function getRequestMiddlewareData(req) {
    let {body, query, params} = req;
    let RequestSourceDataArray = {body, query, params};
    let getRequestMiddlewareDataTools = this;
    let ToolKit = getRequestMiddlewareDataTools.lightCopy(getRequestMiddlewareDataTools);
    ToolKit.DataTypeDetect({
        _GlobalOperate: {
            enableDict: true, bind: {
                String: {aliasVal: "str", aliasDsc: "为字符串类型"},
                Array: {aliasVal: "arr", aliasDsc: "为数组类型"},
                Object: {aliasVal: "obj", aliasDsc: "为对象类型"},
                Boolean: {aliasVal: "boo", aliasDsc: "为布尔类型"},
                Number: {aliasVal: "num", aliasDsc: "为数字类型"},
                Undefined: {aliasVal: "und", aliasDsc: "未知定义类型"},
                Function: {aliasVal: "fun", aliasDsc: "为函数类型"},
                AsyncFunction: {aliasVal: "anf", aliasDsc: "为异步函数类型"},
                Null: {aliasVal: "nul", aliasDsc: "为空数据类型"},
                process: {aliasVal: "pro", aliasDsc: "Node JS Process对象"}
            }, RetValueType: 0
        }
    });

    let ExistDataCount = 0;
    let ExistDataTypeName = [];
    let FinalReturnData;
    for (let detectRequest in RequestSourceDataArray) {
        if (ToolKit.emptyObjectDetect(RequestSourceDataArray[detectRequest]) === false) {
            ExistDataTypeName[ExistDataCount] = detectRequest;
            ExistDataCount++;
        }
    }
    if (ExistDataCount === 1) {
        FinalReturnData = ToolKit.DeepCopyInstance(RequestSourceDataArray[ExistDataTypeName[0]]);
    } else if (ExistDataCount > 1) {
        for (let dci = 0; dci < ExistDataCount; dci++) {
            if (Object.prototype.toString.call(FinalReturnData) !== "[object Array]") {
                FinalReturnData = [];
            }
            FinalReturnData[dci] = ToolKit.DeepCopyInstance(RequestSourceDataArray[ExistDataTypeName[dci]]);
        }
    } else {
        FinalReturnData = null;
    }
    return FinalReturnData;
}

/**
 *获取网站接口请求的数据
 * @param request 客户传参响应对象
 * @return Object|Array
 * @description 用于获取网站接口客户请求发送的非Form-Data数据，没有获取到数据，将抛出异常
 *  */
function getClientRequestData(request) {
    function notEmptyChk(objectOrArray) {
        var count = 0;
        switch (Object.prototype.toString.call(objectOrArray)) {
            case "[object Object]":
                for (var item in objectOrArray) {
                    count++;
                    if (count > 0) {
                        break;
                    }
                }
                return count > 0;
            case "[object Array]":
                count = objectOrArray.length;
                return count > 0;
            default:
                throw new Error("Param It Not Object And Not Array");
        }
    }

    function dc(InstanceSource) {
        try {
            var convert = JSON.stringify(InstanceSource);
            return JSON.parse(convert);
        } catch (e) {
            return InstanceSource;
        }
    }

    function infoBody(type) {
        if (!type) {
            type = "query"
        }
        return {
            type: type,
            content: undefined
        }
    }

    if (Object.prototype.toString.call(request) === "[object Object]") {
        var final_body;
        var notEmpty;
        var p_count = 0;
        var tmp_1;
        var tmp_2;
        var tmp_3;
        try {
            notEmpty = notEmptyChk(request.query);
            if (notEmpty) {
                tmp_1 = dc(request.query);
                p_count++;
            }
        } catch (e) {
            notEmpty = false;
        }
        try {
            notEmpty = notEmptyChk(request.body);
            if (notEmpty) {
                tmp_2 = dc(request.body);
                p_count++;
            }
        } catch (e) {
            notEmpty = false;
        }
        try {
            notEmpty = notEmptyChk(request.params);
            if (notEmpty) {
                tmp_3 = dc(request.params);
                p_count++;
            }
        } catch (e) {
            notEmpty = false;
        }
        if (p_count > 1) {
            final_body = [];
            if (tmp_1) {
                var r_1 = infoBody("query");
                r_1.content = dc(tmp_1);
                final_body.push(r_1);
            }
            if (tmp_2) {
                var r_2 = infoBody("body");
                r_2.content = dc(tmp_2);
                final_body.push(r_2);
            }
            if (tmp_3) {
                var r_3 = infoBody("params")
                r_3.content = dc(tmp_3);
                final_body.push(r_3);
            }
        } else if (p_count > 0) {
            if (tmp_1) {
                final_body = dc(tmp_1);
            }
            if (tmp_2) {
                final_body = dc(tmp_2);
            }
            if (tmp_3) {
                final_body = dc(tmp_3);
            }
        } else {
            throw new Error("No data received");
        }
        return final_body;
    } else {
        throw new Error("Parameter abnormality");
    }
}

/**
 * 获取客户端请求的基本信息
 * @param req 网站访问接口客户端请求传参
 * @return Object
 * */
function clientRequestBaseInfo(req) {
    let infoBody = {
        client_Mozilla_version: undefined,
        client_AppleWebKit_version: undefined,
        client_Chrome_version: undefined,
        client_Safari_version: undefined,
        client_languageUser: "",
        client_doNotTrack: false,
        client_mobile: false,
        client_mobile_code: undefined,
        client_Cookies: undefined,
        system_build: undefined,
        system_model: undefined,
        system_name: undefined,
        system_platform: undefined,
        system_processType: undefined,
        system_window: undefined,
    }

    function notEmptyChk(objectOrArray) {
        var count = 0;
        switch (Object.prototype.toString.call(objectOrArray)) {
            case "[object Object]":
                for (var item in objectOrArray) {
                    count++;
                    if (count > 0) {
                        break;
                    }
                }
                return count > 0;
            case "[object Array]":
                count = objectOrArray.length;
                return count > 0;
            default:
                throw new Error("Param It Not Object And Not Array");
        }
    }

    function dc(InstanceSource) {
        try {
            var convert = JSON.stringify(InstanceSource);
            return JSON.parse(convert);
        } catch (e) {
            return InstanceSource;
        }
    }

    if (Object.prototype.toString.call(req) === "[object Object]") {
        if (notEmptyChk(req)) {
            infoBody.client_languageUser = String(req.headers["accept-language"]).split(",")[0];
            if (infoBody.client_languageUser === "undefined") {
                infoBody.client_languageUser = undefined;
            }
            if (typeof req.headers.cookie === "string") {
                if (Object.prototype.toString.call(infoBody.client_Cookies) !== "[object Object]") {
                    infoBody.client_Cookies = {};
                }
                let temp1;
                let temp2;
                if (String(req.headers.cookie).indexOf("; ") > -1) {
                    temp1 = String(req.headers.cookie).split("; ");
                    for (let num in temp1) {
                        temp2 = String(temp1[num]).split("=");
                        infoBody.client_Cookies[temp2[0]] = temp2[1];
                    }
                } else {
                    temp2 = String(req.headers.cookie).split("=");
                    infoBody.client_Cookies[temp2[0]] = temp2[1];
                }
            }
            if (parseInt(req.headers.dnt) === 1) {
                infoBody.client_doNotTrack = true;
            }
            let tempData_appVersion = String(req.headers["user-agent"]).split(" ");
            if (String(tempData_appVersion[0]).indexOf("/") > -1) {
                let tmp = String(tempData_appVersion[0]).split("/");
                switch (String(tmp[0]).toLowerCase()) {
                    case "mozilla":
                        infoBody.client_Mozilla_version = tmp[1];
                        break;
                    default:
                        infoBody[String(tmp[0]).toString()] = tmp[1];
                        break;
                }
            } else {
                infoBody.client_Mozilla_version = tempData_appVersion[0];
            }
            tempData_appVersion.shift();
            if (tempData_appVersion.length > 0) {
                let tmp = []
                let count = 0;
                let tms = 0;
                let existLeft = false;
                while (true) {
                    if (String(tempData_appVersion[tms]).indexOf("(") > -1) {
                        existLeft = true;
                        if (typeof tmp[count] !== "object") {
                            tmp[count] = [];
                        }
                        tmp[count].push(tempData_appVersion[tms]);
                        tempData_appVersion.splice(tms, 1);
                    } else if (String(tempData_appVersion[tms]).indexOf(")") > -1) {
                        tmp[count].push(tempData_appVersion[tms]);
                        tempData_appVersion.splice(tms, 1);
                        count++;
                        existLeft = false;
                    } else {
                        if (existLeft) {
                            if (typeof tempData_appVersion[tms] === "undefined") {
                                break;
                            } else {
                                tmp[count].push(tempData_appVersion[tms]);
                                tempData_appVersion.splice(tms, 1);
                            }
                        } else {
                            if (tms >= tempData_appVersion.length) {
                                break;
                            }
                            tms++;
                        }
                    }
                }
                for (let num in tmp) {
                    tmp[num] = tmp[num].join(',');
                    if (String(tmp[num]).charAt(0) === "(" && String(tmp[num]).charAt(String(tmp[num]).length - 1) === ")") {
                        tmp[num] = String(tmp[num]).substr(1, String(tmp[num]).length - 2);
                    }
                }
                for (let num in tmp) {
                    tmp[num] = String(tmp[num]).split(',');
                    tmp[num] = String(tmp[num]).split(',');
                }
                for (let num in tmp) {
                    tmp[num].forEach((value, index, array) => {
                        switch (value) {
                            case "":
                                array.splice(index, 1);
                                break;
                            default:
                                if (String(value).indexOf("/") > -1) {
                                    tempData_appVersion.push(value);
                                    array.splice(index, 1);
                                }
                                break;
                        }
                    });
                }
                for (let num in tmp) {
                    tmp[num].forEach((value, index, array) => {
                        if (String(value).indexOf("/") > -1) {
                            let notExists = true;
                            tempData_appVersion.forEach((v1, i1, a1) => {
                                if (v1 === value) {
                                    notExists = false;
                                    throw new Error("");
                                }
                            });
                            if (notExists) {
                                tempData_appVersion.push(value);
                            }
                        }
                    });
                }
                for (let num in tempData_appVersion) {
                    if (String(tempData_appVersion[num]).indexOf("/") > -1) {
                        let tmp = String(tempData_appVersion[num]).split("/");
                        switch (String(tmp[0]).toLowerCase()) {
                            case "applewebkit":
                                infoBody.client_AppleWebKit_version = tmp[1];
                                break;
                            case "chrome":
                                infoBody.client_Chrome_version = tmp[1];
                                break;
                            case "safari":
                                infoBody.client_Safari_version = tmp[1];
                                break;
                            case "mobile":
                                infoBody.client_mobile = true;
                                infoBody.client_mobile_code = tmp[1];
                                break;
                            case "build":
                                if (String(tmp[1]).charAt(String(tmp[1]).length - 1) === ";") {
                                    infoBody.system_build = String(tmp[1]).substr(0, String(tmp[1]).length - 1);
                                } else {
                                    infoBody.system_build = tmp[1];
                                }
                                break;
                            default:
                                infoBody[String(tmp[0]).toString()] = tmp[1];
                                break;
                        }
                    } else {
                        switch (String(tempData_appVersion[num]).toLowerCase()) {
                            case "mobile":
                                infoBody.client_mobile = true;
                                break;
                        }
                    }
                }
                if (infoBody.client_mobile) {
                    infoBody.system_window = String(tmp[0][0]).substr(0, String(tmp[0][0]).length - 1);
                    tmp[0].shift();
                    let tmp1 = [], es = 0, ols = undefined;
                    while (true) {
                        if (String(tmp[0][es]).indexOf(";") > -1) {
                            ols += " " + String(tmp[0][es]).substr(0, String(tmp[0][es]).length - 1);
                            tmp1.push(ols);
                            tmp[0].splice(0, (es + 1));
                            es = 0;
                            ols = undefined;
                        } else {
                            if (es > (tmp[0].length - 1)) {
                                tmp1.push(ols);
                                break;
                            } else {
                                if (ols === undefined) {
                                    ols = "";
                                    ols += tmp[0][es];
                                } else {
                                    ols += " " + tmp[0][es];
                                }
                            }
                            es++;
                        }
                    }
                    infoBody.system_model = tmp1[1];
                    infoBody.system_name = tmp1[0];
                } else {
                    infoBody.system_window = String(tmp[0][0]).substr(0, String(tmp[0][0]).length - 1);
                    tmp[0].splice(0, 1);
                    infoBody.system_processType = tmp[0][1];
                    infoBody.system_name = tmp[0][0];
                }
            }
            return infoBody;
        }
    } else {
        throw new Error("Parameter abnormality");
    }
}


/**
 * 生成文件下载响应信息对象
 * @param FileName : string 需要生成下载响应信息对象的文件名称
 * @param {[{extName:string,body:Object,format:string}]} customHeaderLib : Array 自定义下载响应信息对象数据源
 * @description 本函数已经内置多种文件类型的响应信息的数据，可以满足大部分的需求
 * @return Object
 * */
function makeResponseHeaderInfo(FileName, customHeaderLib) {
    let DefineDetect = (Source) => {
        let FinalDetect;
        try {
            if (Object.prototype.toString.call(Source) === "[object Array]") {
                FinalDetect = [];
                Source.forEach((value, index, array) => {
                    if (Object.prototype.toString.call(value) === "[object Object]") {
                        let tmp = {};
                        let count = 0;
                        for (let num in value) {
                            switch (String(num).toLowerCase()) {
                                case "extname":
                                    if (Object.prototype.toString.call(value[num]) === "[object String]") {
                                        tmp.extName = value[num];
                                    } else {
                                        throw new Error("");
                                    }
                                    count++;
                                    break;
                                case "body":
                                    if (Object.prototype.toString.call(value[num]) === "[object Object]") {
                                        tmp.body = {};
                                        for (let item in value[num]) {
                                            switch (String(item).toLowerCase()) {
                                                case "content-type":
                                                    tmp.body["Content-Type"] = value[num][item];
                                                    break;
                                                case "content-disposition":
                                                    tmp.body["Content-Disposition"] = value[num][item];
                                                    break;
                                                default:
                                                    throw new Error("");
                                            }
                                        }
                                    } else {
                                        throw new Error("");
                                    }
                                    count++;
                                    break;
                                case "format":
                                    if (Object.prototype.toString.call(value[num]) === "[object String]") {
                                        tmp.format = value[num];
                                    } else {
                                        throw new Error("");
                                    }
                                    count++;
                                    break;
                                default:
                                    throw new Error("");
                            }
                        }
                        if (count === 3) {
                            FinalDetect.push(tmp);
                        } else {
                            throw new Error("")
                        }
                    } else {
                        throw new Error("");
                    }
                });
                return FinalDetect;
            } else {
                throw new Error("");
            }
        } catch (e) {
            FinalDetect = undefined;
        }
        return FinalDetect;
    }
    let getExtName = (SourceName) => {
        if (String(SourceName).indexOf(".") > -1) {
            let tmp;
            for (let num = String(SourceName).length - 1; num >= 0; num--) {
                if (String(SourceName).charAt(num) === ".") {
                    tmp = String(SourceName).substr(num + 1);
                    break;
                }
            }
            return tmp;
        } else {
            return undefined;
        }
    }
    let foundMatch = false;
    let HeaderInfoLib;
    let FinalResponseBody = {
        body: {
            'Content-Type': '',
            'Content-Disposition': 'attachment; filename='
        },
        format: ""
    }

    function processResponseObject() {
        HeaderInfoLib.forEach((value, index, array) => {
            if (String(value.extName).toLowerCase().includes(String(getExtName(FileName)).toLowerCase())) {
                foundMatch = true;
                FinalResponseBody.format = value.format;
                FinalResponseBody.body["Content-Disposition"] = value.body["Content-Disposition"] + encodeURI(FileName);
                FinalResponseBody.body["Content-Type"] = value.body["Content-Type"]
            }
        });
    }

    if (DefineDetect(customHeaderLib)) {
        HeaderInfoLib = DefineDetect(customHeaderLib);
        processResponseObject();
    } else {
        HeaderInfoLib = [
            {
                extName: 'txt,log',
                body: {
                    'Content-Type': 'text/plain',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'json',
                body: {
                    'Content-Type': 'application/json',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'reg',
                body: {
                    'Content-Type': 'text/x-ms-regedit',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'md',
                body: {
                    'Content-Type': 'text/markdown',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'htm,html',
                body: {
                    'Content-Type': 'text/html',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'xml',
                body: {
                    'Content-Type': 'text/xml',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'js',
                body: {
                    'Content-Type': 'text/javascript',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'css',
                body: {
                    'Content-Type': 'text/css',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'scss',
                body: {
                    'Content-Type': 'text/x-scss',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'utf8'
            },
            {
                extName: 'wma',
                body: {
                    'Content-Type': 'audio/x-ms-wma',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'mid',
                body: {
                    'Content-Type': 'audio/midi',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'mp3',
                body: {
                    'Content-Type': 'audio/mpeg',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'wmv',
                body: {
                    'Content-Type': 'video/x-ms-wmv',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'avi',
                body: {
                    'Content-Type': 'video/x-msvideo',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'mp4',
                body: {
                    'Content-Type': 'video/mp4',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'jpg,jpeg',
                body: {
                    'Content-Type': 'image/jpeg',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'png',
                body: {
                    'Content-Type': 'image/png',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'gif',
                body: {
                    'Content-Type': 'image/gif',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'webp',
                body: {
                    'Content-Type': 'image/webp',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'psd',
                body: {
                    'Content-Type': 'image/vnd.adobe.photoshop',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'cur',
                body: {
                    'Content-Type': 'image/x-win-bitmap',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'bmp',
                body: {
                    'Content-Type': 'image/bmp',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'ttf',
                body: {
                    'Content-Type': 'font/ttf',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'woff',
                body: {
                    'Content-Type': 'font/woff',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'woff2',
                body: {
                    'Content-Type': 'font/woff2',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'ttc',
                body: {
                    'Content-Type': 'font/collection',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'pdf',
                body: {
                    'Content-Type': 'application/pdf',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'doc,docx',
                body: {
                    'Content-Type': 'application/msword',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'zip',
                body: {
                    'Content-Type': 'application/zip',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: '7z',
                body: {
                    'Content-Type': 'application/x-7z-compressed',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'exe',
                body: {
                    'Content-Type': 'application/x-ms-dos-executable',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'jar',
                body: {
                    'Content-Type': 'application/x-java-archive',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'crx',
                body: {
                    'Content-Type': 'application/x-chrome-extension',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'php',
                body: {
                    'Content-Type': 'application/x-php',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'sql',
                body: {
                    'Content-Type': 'application/sql',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'svg',
                body: {
                    'Content-Type': 'image/svg+xml',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            },
            {
                extName: 'img',
                body: {
                    'Content-Type': 'application/x-raw-disk-image',
                    'Content-Disposition': 'attachment; filename='
                },
                format: 'binary'
            }
        ];
        processResponseObject();
    }
    if (!foundMatch) {
        FinalResponseBody.body["Content-Type"] = "application/octet-stream";
        FinalResponseBody.body["Content-Disposition"] = `attachment; filename=${encodeURI(FileName)}`;
        FinalResponseBody.format = "binary";
    }
    return FinalResponseBody;
}

module.exports = {
    clientRequestBaseInfo,
    getRequestMiddlewareData,
    getClientRequestData,
    makeResponseHeaderInfo,
    webServerFileUpdateModule,
    webServerDataUpdate,
    wakeUpCurrentNetworkPointHost,
    wakeUpCurrentNetworkALLHost
};